﻿using System.Collections;
using System.Diagnostics;
using System.Security.Cryptography;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp;
using Xunit;
using static System.Runtime.InteropServices.JavaScript.JSType;


namespace MyWatermark
{

    public class DebugInfo
    {
        public int ErrorBits { get; set; }
        public int TotalBits { get; set; }

        public double Psnr { get; set; }

        public string Note { get; set; }
    }



    public class mainmain
    {
        public static void TestAttackResilience()
        {
            string rootPath = @"D:\ywd\work\ncs\新水印的尝试\MyWatermark\gitee\pic";

            string hostPath = $@"{rootPath}\original.jpg";

            // 原始图像和水印
            byte[] original = File.ReadAllBytes(hostPath);
            var watermark = WatermarkCore.TextToBinaryWithHeader("AttackTest@2024");

            // 嵌入水印
            byte[] watermarked = WatermarkCore.Embed(watermark, original);

            // 模拟攻击流程
            byte[] attacked = watermarked;

            // 1. 缩放攻击（缩小到80%）
            attacked = TestTools.ResizeImage(attacked, 0.8);

            // 2. 中心裁剪（保留60%）
            attacked = TestTools.CropCenter(attacked, 0.6);

            // 3. JPEG压缩（模拟质量损失）
            attacked = TestTools.ConvertToJpeg(attacked, 75); // 需要添加此方法

            // 提取水印
            BitArray extracted = WatermarkCore.Extract(attacked);
            string result = WatermarkCore.BinaryToTextWithHeader(extracted);
            Console.WriteLine($"攻击后提取结果: {result}");

            return;
        }

        // 添加调试方法
        public static void ValidateBlockOrder(string hostPath)
        {
            Image<Bgra32> image = Image.Load<Bgra32>(hostPath);
            var generator = new BlockGenerator();
            var blocks1 = WatermarkCore.GetConsistentBlockOrder(image);



            var watermark = WatermarkCore.TextToBinaryWithHeader(GenerateTimestampedCode());
            byte[] original = original = File.ReadAllBytes(hostPath);
            // 嵌入水印
            byte[] watermarked = WatermarkCore.Embed(watermark, original);
            Image<Bgra32> image2 = Image.Load<Bgra32>(watermarked);


            var blocks2 = WatermarkCore.GetConsistentBlockOrder(image2);



            // 生成可视对比图
            var visual1 = generator.VisualizeBlocks(image.Clone(), blocks1.Values);
            var visual2 = generator.VisualizeBlocks(image2.Clone(), blocks2.Values);
            visual1.Save("visual1.png");
            visual2.Save("visual2.png");

            var pairs = blocks1.Zip(blocks2, (a, b) => new { A = a, B = b });
            foreach (var pair in pairs)
            {
                if (pair.A.Key.X != pair.B.Key.X || pair.A.Key.Y != pair.B.Key.Y)
                {

                }
            }
        }

        public static void NormalTest(string fileName, string ext)
        {
            string rootPath = @"D:\ywd\work\ncs\新水印的尝试\MyWatermark\gitee\pic";

            string hostPath = $@"{rootPath}\{fileName}.{ext}";
            string outPath = $@"{rootPath}\{fileName}_out.{ext}";

            var watermark = WatermarkCore.TextToBinaryWithHeader(GenerateTimestampedCode());
            int bitArrayLength = watermark.Count;

            // 创建一个新的 Stopwatch 实例
            Stopwatch stopwatch = new Stopwatch();
            // 开始计时
            stopwatch.Start();

            byte[] original = original = File.ReadAllBytes(hostPath);
            // 嵌入水印
            byte[] watermarked = WatermarkCore.Embed(watermark, original);

            File.WriteAllBytes($@"{rootPath}\outer.jpg", watermarked);

            // 提取水印
            BitArray extracted = WatermarkCore.Extract(watermarked);

            // 停止计时
            stopwatch.Stop();
            // 打印运行时间
            Console.WriteLine(hostPath);
            Console.WriteLine($"运行时间: {stopwatch.ElapsedMilliseconds} 毫秒");

            // 计算误码率
            if (extracted.Length != watermark.Count)
            {
                Console.WriteLine($"解析失败");
            }
            else
            {
                int errors = 0;
                for (int i = 0; i < bitArrayLength; i++)

                    if (watermark[i] != extracted[i])
                        errors++;

                Console.WriteLine($"误码数:{errors}，误码率: {errors / (double)bitArrayLength:P}");
                Console.WriteLine($"PSNR: {TestTools.CalculatePsnr(original, watermarked):F2}dB");
                var tt = WatermarkCore.BinaryToTextWithHeader(extracted);
                Console.WriteLine($"解析结果:{tt}");
            }
            Console.WriteLine();
        }

        public static void NormalExtractTest(string fileName, string ext)
        {
            string rootPath = @"D:\ywd\work\ncs\新水印的尝试\MyWatermark\gitee\pic";

            string hostPath = $@"{rootPath}\{fileName}.{ext}";


            // 创建一个新的 Stopwatch 实例
            Stopwatch stopwatch = new Stopwatch();
            // 开始计时
            stopwatch.Start();

            byte[] original = original = File.ReadAllBytes(hostPath);
            // 嵌入水印

            // 提取水印
            BitArray extracted = WatermarkCore.Extract(original);

            // 停止计时
            stopwatch.Stop();
            // 打印运行时间
            Console.WriteLine(hostPath);
            Console.WriteLine($"运行时间: {stopwatch.ElapsedMilliseconds} 毫秒");

            // 计算误码率
            if (extracted.Length == 0)
            {
                Console.WriteLine($"解析失败");
            }
            else
            {


                var tt = WatermarkCore.BinaryToTextWithHeader(extracted);
                Console.WriteLine($"解析结果:{tt}");
            }
            Console.WriteLine();
        }



        public static void NormalTestTwice(string fileName, string ext)
        {
            string rootPath = @"D:\ywd\work\ncs\新水印的尝试\MyWatermark\gitee\pic";

            string hostPath = $@"{rootPath}\{fileName}.{ext}";
           

            byte[] watermarked;


            {
                string outPath = $@"{rootPath}\{fileName}_out1.{ext}";
                var watermark1 = WatermarkCore.TextToBinaryWithHeader(GenerateTimestampedCode());
                int bitArrayLength1 = watermark1.Count;

                // 创建一个新的 Stopwatch 实例
                Stopwatch stopwatch = new Stopwatch();
                // 开始计时
                stopwatch.Start();

                byte[] original = original = File.ReadAllBytes(hostPath);
                // 嵌入水印
                watermarked = WatermarkCore.Embed(watermark1, original);

                File.WriteAllBytes(outPath, watermarked);

                // 提取水印
                BitArray extracted = WatermarkCore.Extract(watermarked);

                // 停止计时
                stopwatch.Stop();
                // 打印运行时间
                //Console.WriteLine(hostPath);
                Console.WriteLine($"二次水印测试:");
                Console.WriteLine($"第一次:");
                //Console.WriteLine($"运行时间: {stopwatch.ElapsedMilliseconds} 毫秒");

                // 计算误码率
                if (extracted.Length != watermark1.Count)
                {
                    Console.WriteLine($"解析失败");
                }
                else
                {
                    int errors = 0;
                    for (int i = 0; i < bitArrayLength1; i++)

                        if (watermark1[i] != extracted[i])
                            errors++;

                    Console.WriteLine($"误码数:{errors}，误码率: {errors / (double)bitArrayLength1:P}");
                    Console.WriteLine($"PSNR: {TestTools.CalculatePsnr(original, watermarked):F2}dB");
                    var tt = WatermarkCore.BinaryToTextWithHeader(extracted);
                    Console.WriteLine($"解析结果:{tt}");
                }


            }


            {
                string outPath = $@"{rootPath}\{fileName}_out2.{ext}";
                var watermark1 = WatermarkCore.TextToBinaryWithHeader(GenerateTimestampedCode());
                int bitArrayLength1 = watermark1.Count;
                // 创建一个新的 Stopwatch 实例
                Stopwatch stopwatch = new Stopwatch();
                // 开始计时
                stopwatch.Start();

                // 嵌入水印
                byte[] watermarked2 = WatermarkCore.Embed(watermark1, watermarked);

                File.WriteAllBytes(outPath, watermarked2);

                // 提取水印
                BitArray extracted = WatermarkCore.Extract(watermarked2);

                // 停止计时
                stopwatch.Stop();
                // 打印运行时间
                //Console.WriteLine(hostPath);
                Console.WriteLine($"第二次:");
                //Console.WriteLine($"运行时间: {stopwatch.ElapsedMilliseconds} 毫秒");

                // 计算误码率
                if (extracted.Length != watermark1.Count)
                {
                    Console.WriteLine($"解析失败");
                }
                else
                {
                    int errors = 0;
                    for (int i = 0; i < bitArrayLength1; i++)

                        if (watermark1[i] != extracted[i])
                            errors++;

                    Console.WriteLine($"误码数:{errors}，误码率: {errors / (double)bitArrayLength1:P}");
                    Console.WriteLine($"PSNR: {TestTools.CalculatePsnr(watermarked, watermarked2):F2}dB");
                    var tt = WatermarkCore.BinaryToTextWithHeader(extracted);
                    Console.WriteLine($"解析结果:{tt}");
                }

                Console.WriteLine();
            }
        }


        public static void main()
        {
            ValidateBlockOrder(@"D:\ywd\work\ncs\新水印的尝试\MyWatermark\gitee\pic\3.png");

            //using var image = Image.Load<Bgra32>(@"D:\ywd\work\ncs\新水印的尝试\MyWatermark\gitee\pic\3.png");

            //// 生成冗余区块
            //var generator = new BlockGenerator();
            //var blocks = generator.GenerateRedundantBlocks(image);

            //// 可视化结果（可选）
            //var resultImage = generator.VisualizeBlocks(image.Clone(), blocks.Values);
            //resultImage.SaveAsWebp(@"D:\ywd\work\ncs\新水印的尝试\MyWatermark\gitee\pic\output.webp");

            //抗噪测试，高斯噪声，jpeg压缩
            //TestTools.TestNoiseResistance();

            //几何攻击测试
            //TestTools.TestGeometricResistance();






            string rootPath = @"D:\ywd\work\ncs\新水印的尝试\MyWatermark\gitee\pic";

            string hostPath = $@"{rootPath}\original.jpg";
            string outPath = $@"{rootPath}\outer.jpg";

            // 生成测试图像

            //var watermark = WatermarkCore.TextToBinaryWithHeader("sukimikuru 01234567899!@#$%^$&*(O))");

            var guid = Guid.NewGuid();
            string shortGuid = Convert.ToBase64String(guid.ToByteArray())
       .Replace("+", "-")
       .Replace("/", "_")
       .Substring(0, 22); // 移除末尾的填充符
            var watermark = WatermarkCore.TextToBinaryWithHeader(GenerateTimestampedCode());
            int bitArrayLength = watermark.Count;
            //var t = WatermarkCore.BinaryToTextWithHeader(watermark);



            ////基础超级大图
            //{
            //    // 创建一个新的 Stopwatch 实例
            //    Stopwatch stopwatch = new Stopwatch();
            //    // 开始计时
            //    stopwatch.Start();

            //    byte[] original = original = File.ReadAllBytes($@"{rootPath}\UX303_Family_2 (2) no water.jpg");

            //    long saveFileProcessTime;

            //    // 嵌入水印
            //    byte[] watermarked = WatermarkCore.Embed(watermark, original, out saveFileProcessTime);

            //    File.WriteAllBytes($@"{rootPath}\ROG_Asymmetry_Windbreaker5_outer.jpg", watermarked);

            //    // 提取水印
            //    BitArray extracted = WatermarkCore.Extract(watermarked);

            //    // 计算误码率
            //    int errors = 0;
            //    for (int i = 0; i < bitArrayLength; i++)

            //        if (watermark[i] != extracted[i])
            //            errors++;

            //    // 停止计时
            //    stopwatch.Stop();
            //    // 获取运行时间（以毫秒为单位）
            //    long elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
            //    // 打印运行时间
            //    Console.WriteLine($"超级大图运行时间: {elapsedMilliseconds} 毫秒,saveFileProcessTime:{saveFileProcessTime}");

            //    Console.WriteLine("3.jpeg");
            //    Console.WriteLine($"误码数:{errors}，误码率: {errors / (double)bitArrayLength:P}");
            //    Console.WriteLine($"PSNR: {TestTools.CalculatePsnr(original, watermarked):F2}dB");
            //    var tt = WatermarkCore.BinaryToTextWithHeader(extracted);
            //    Console.WriteLine($"解析结果:{tt}");
            //    Console.WriteLine();
            //    return;
            //}


            ////纯色测试图
            //{
            //    // 创建一个新的 Stopwatch 实例
            //    Stopwatch stopwatch = new Stopwatch();
            //    // 开始计时
            //    stopwatch.Start();

            //    byte[] original = TestTools.GenerateSolidColorImage(512, 512, 128, 128, 128);
            //    // 嵌入水印

            //    byte[] watermarked = WatermarkCore.Embed(watermark, original);

            //    File.WriteAllBytes($@"{rootPath}\outergreen.jpg", watermarked);

            //    // 提取水印
            //    BitArray extracted = WatermarkCore.Extract(watermarked);

            //    // 计算误码率
            //    int errors = 0;
            //    for (int i = 0; i < bitArrayLength; i++)

            //        if (watermark[i] != extracted[i]) errors++;

            //    // 停止计时
            //    stopwatch.Stop();
            //    // 获取运行时间（以毫秒为单位）
            //    long elapsedMilliseconds = stopwatch.ElapsedMilliseconds;
            //    // 打印运行时间
            //    Console.WriteLine($"运行时间: {elapsedMilliseconds} 毫秒");


            //    Console.WriteLine("绿图");
            //    Console.WriteLine($"误码数:{errors}，误码率: {errors / (double)bitArrayLength:P}");
            //    Console.WriteLine($"PSNR: {TestTools.CalculatePsnr(original, watermarked):F2}dB");
            //    var tt = WatermarkCore.BinaryToTextWithHeader(extracted);
            //    Console.WriteLine($"解析结果:{tt}");
            //    Console.WriteLine();

            //}

            //基础测试图
            {
                //NormalExtractTest("222", "jpg");

                NormalTestTwice("original", "jpg");

                NormalTestTwice("3", "jpeg");

                NormalTestTwice("3", "png");

                NormalTestTwice("test1", "jpg");

            }



            
            //TestTools.ValidateColorConversion();
            //TestTools.ValidateDctIdct();
            //TestTools.FullValidationTest();




        }

        public static string GenerateTimestampedCode()
        {
            long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
            string timePart = Base62Encode(timestamp).Substring(0, 6);
            string randomPart = GenerateShortRandom(4);
            return timePart + randomPart;
        }

        // 使用Base62编码（数字+大小写字母）
        public static string GenerateShortRandom(int length = 6)
        {
            const string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
            char[] result = new char[length];

            using (var rng = RandomNumberGenerator.Create())
            {
                byte[] uintBuffer = new byte[sizeof(uint)];

                for (int i = 0; i < length; i++)
                {
                    rng.GetBytes(uintBuffer);
                    uint num = BitConverter.ToUInt32(uintBuffer, 0);
                    result[i] = chars[(int)(num % (uint)chars.Length)];
                }
            }

            return new string(result);
        }

        // Base62编码工具方法
        private static string Base62Encode(long value)
        {
            const string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
            char[] result = new char[8];

            for (int i = 7; i >= 0; i--)
            {
                result[i] = chars[(int)(value % 62)];
                value /= 62;
            }

            return new string(result).TrimStart('0');
        }

    }
}
